package communication;

import java.io.IOException ;

import jaxcentServer.ServerMain ;
import util.Log ;
import util.Subsystem ;
import domain.ForumLogic ;

/**
 * server responsible for http clients.
 * @author idan
 */
public class Webserver
{

	private static final String DEFAULT_CONFIG_FILE_PATH = "html/JaxcentConfig.xml" ;
	private static final String DEFAULT_PAGE_RENDERER_CLASSPATH = "tgt/presentation/web" ;
	private static final String DEFAULT_HTML_PATH = "html" ;
	private static final int DEFAULT_HTTP_PORT = 8080 ;

	private static ForumLogic forumLogic ;

	private String htmlPath ;
	private String pageRendererClasspath ;
	private int port ;

	private String configFilePath ;
	private ServerMain jaxcentServer ;

	/**
	 * @return the forum object this server is connected to.
	 */
	public static ForumLogic getForumLogic()
	{
		return Webserver.forumLogic ;
	}

	/**
	 * set the webserver with default settings.
	 * @param forumLogic forum with which the server communicates.
	 * @throws IOException if the server could not be started due to network problems.
	 */
	public Webserver(final ForumLogic forumLogic) throws IOException
	{
		this(Webserver.DEFAULT_HTML_PATH, Webserver.DEFAULT_PAGE_RENDERER_CLASSPATH,
			Webserver.DEFAULT_HTTP_PORT, Webserver.DEFAULT_CONFIG_FILE_PATH, forumLogic) ;
	}

	/**
	 * @param htmlPath path in which html files reside.
	 * @param pageRendererClasspath path in which bytecode to generate the pages resides.
	 * @param port port on which the server listens.
	 * @param configFilePath path to the config file to use for jaxcent.
	 * @param forumLogic forum with which the server communicates.
	 * @throws IOException if the server could not be started due to network problems.
	 */
	public Webserver(final String htmlPath, final String pageRendererClasspath, final int port,
		final String configFilePath, final ForumLogic forumLogic) throws IOException
	{
		super() ;
		Webserver.forumLogic = forumLogic ;

		this.htmlPath = htmlPath ;
		this.pageRendererClasspath = pageRendererClasspath ;
		this.port = port ;
		this.configFilePath = configFilePath ;
	}

	/**
	 * @return path in which the configuration file resides.
	 */
	public String getConfigFilePath()
	{
		return this.configFilePath ;
	}

	/**
	 * @return path in which the html files reside.
	 */
	public String getHtmlPath()
	{
		return this.htmlPath ;
	}

	/**
	 * @return path in which the bytecode to render html pages is in.
	 */
	public String getPageRendererClasspath()
	{
		return this.pageRendererClasspath ;
	}

	/**
	 * @return port on which the server listens.
	 */
	public int getPort()
	{
		return this.port ;
	}

	/**
	 * restart the server.
	 * @throws IOException if network condition do not enable starting of the server.
	 * @post webserver is on.
	 */
	public void restart() throws IOException
	{
		this.stop() ;
		this.start() ;
	}

	/**
	 * @param configFilePath new config file for the server.
	 * @throws IOException if the server could not restart with the new config file.
	 * @post this.getConfigFilePath() == configFilePath.
	 */
	public void setConfigFilePath(final String configFilePath) throws IOException
	{
		this.configFilePath = configFilePath ;
		this.restart() ;
	}

	/**
	 * @param htmlPath new path for html files.
	 * @throws IOException if the server could not adjust to the new path.
	 * @post this.getHtmlPath() == htmlPath
	 */
	public void setHtmlPath(final String htmlPath) throws IOException
	{
		this.htmlPath = htmlPath ;
		this.restart() ;
	}

	/**
	 * @param pageRendererClasspath new classpath for the page rendering bytecode.
	 * @throws IOException if the server could not adjust to the new classpath.
	 * @post this.getPageRendererClasspath() == pageRendererClasspath.
	 */
	public void setPageRendererClasspath(final String pageRendererClasspath) throws IOException
	{
		this.pageRendererClasspath = pageRendererClasspath ;
		this.restart() ;
	}

	/**
	 * @param port new port.
	 * @throws IOException if the server could not adjust to the new port.
	 * @post this.getPort() = port.
	 */
	public void setPort(final int port) throws IOException
	{
		this.port = port ;
		this.restart() ;
	}

	/**
	 * start the server.
	 * @throws IOException if network condition do not allow starting the server.
	 * @pre webserver is off.
	 * @post webserver is on.
	 */
	public void start() throws IOException
	{
		if (this.jaxcentServer != null)
		{
			throw new IllegalStateException("starting an already started server") ;
		}
        this.jaxcentServer = new ServerMain(this.port, this.htmlPath, this.configFilePath, this.pageRendererClasspath) ;
        this.jaxcentServer.start();
	}

	/**
	 * stop the server.
	 * @pre webserver is on.
	 * @post webserver is off.
	 */
	public void stop()
	{
		try
		{
			if (this.jaxcentServer != null)
			{
				this.jaxcentServer.terminate() ;
				this.jaxcentServer = null ;
			}
		}
		catch (IOException e)
		{
			Log.getLogger(Subsystem.COMMUNICATION).warning("unable to stop web server: " + e) ;
		}
	}

	/**
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString()
	{
		return String.valueOf(this.getPort()) ;
	}
}
